package cn.lzm.server.tcp;

import cn.hutool.core.exceptions.ExceptionUtil;
import cn.lizemin.entity.RpcRequest;
import cn.lizemin.entity.RpcResponse;
import cn.lzm.protocol.ProtocolMessage;
import cn.lzm.protocol.ProtocolMessageDecoder;
import cn.lzm.protocol.ProtocolMessageEncoder;
import cn.lzm.protocol.ProtocolMessageTypeEnum;
import cn.lzm.registry.LocalRegistry;
import io.vertx.core.Handler;
import io.vertx.core.buffer.Buffer;
import io.vertx.core.net.NetSocket;

import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

/**
 * @author lzm
 * @Date 2024/11/6
 * @description TCP请求处理器
 */
public class TcpServerHandler implements Handler<NetSocket> {

    @Override
    public void handle(NetSocket socket) {
        TcpBufferHandlerWrapper bufferHandler = new TcpBufferHandlerWrapper(buffer -> {
            ProtocolMessage<RpcRequest> protocolMessage;
            try {
                protocolMessage = (ProtocolMessage<RpcRequest>) ProtocolMessageDecoder.decode(buffer);
            } catch (IOException e) {
                throw new RuntimeException("协议消息解码错误");
            }
            RpcRequest request = protocolMessage.getBody();
            Class<?> implClass = LocalRegistry.get(request.getServiceName());
            RpcResponse response = new RpcResponse();
            try {
                Method method = implClass.getDeclaredMethod(request.getMethodName(), request.getArgTypes());
                Object result = method.invoke(implClass.getDeclaredConstructor().newInstance(), request.getArgs());
                response.setData(result);
                response.setDataType(method.getReturnType());
                response.setMessage("ok");
            } catch (NoSuchMethodException | InvocationTargetException | IllegalAccessException |
                     InstantiationException e) {
                response.setException(e);
                response.setMessage(e.getMessage());
                System.out.println(ExceptionUtil.getThrowableList(e));
            }

            ProtocolMessage.Header header = protocolMessage.getHeader();
            header.setType((byte) ProtocolMessageTypeEnum.RESPONSE.getKey());
            ProtocolMessage<RpcResponse> respMessage = new ProtocolMessage<>(header, response);
            try {
                Buffer respBuffer = ProtocolMessageEncoder.encode(respMessage);
                socket.write(respBuffer);
            } catch (IOException e) {
                throw new RuntimeException("协议消息编码错误");
            }
        });
        socket.handler(bufferHandler);
    }
}
